package com.dorm.cj.design;

import com.dorm.cj.design.module.BigDecimalModule;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.guava.GuavaModule;

import java.io.IOException;

/**
 * 序列化和反序列化时，需要自定义解析规则时，要手动注册自己的module
 */
public class JsonMapper {

    private ObjectMapper objectMapper = new ObjectMapper();

    public static final JsonMapper JSON_MAPPER_NON_EMPTY;

    static {
        JSON_MAPPER_NON_EMPTY = new JsonMapper(JsonInclude.Include.NON_EMPTY);
    }

    private JsonMapper(JsonInclude.Include include) {
        //设置mapper属性
        /*
        ALWAYS,默认
        NON_NULL,属性为null不序列化
        NON_ABSENT,
        NON_EMPTY,属性为空或null不序列化
        NON_DEFAULT,属性为默认值不序列化
        CUSTOM,
        USE_DEFAULTS;
        */
        this.objectMapper.setSerializationInclusion(include);

        this.objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        /*下面两条配置可解决类似sInfoCode解析成sinfoCode的问题*/
        //所有属性和方法 所有类型（public，private）不可自动检测
        this.objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
        //属性字段 任何类型可自动检测
        this.objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

        //注册解析模块
        /*
        另一种方式：比如定制date格式
        @JsonSerialize(using=DemoDateSerializer.class)
    　　@JsonDeserialize(using=DemoDateDeserializer.class)
        作用在属性上可以指定该属性使用特殊的序列化/反序列化方法
        */
        this.objectMapper.registerModule(new BigDecimalModule());
        this.objectMapper.registerModule(new GuavaModule());

        // 该配置可以过滤Map<key,value> 中的value=null
        this.objectMapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
    }

    public String toJson(Object object) {
        try {
            return this.objectMapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return null;
        }
    }

    public <T> T fromJson(String jsonStr, Class<T> z) throws IOException {
        if (jsonStr == null || jsonStr.length() == 0) {
            return null;
        }
        try {
            return this.objectMapper.readValue(jsonStr, z);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("parser jsonStr :" + jsonStr + "to class class::" + z.getName());
            return null;
        }

    }

}
